package com.hibernate.hrm.service.contract;

import com.hibernate.hrm.dao.ContractAttachmentRepository;
import com.hibernate.hrm.dao.ContractRepository;
import com.hibernate.hrm.dao.UserRepository;
import com.hibernate.hrm.entity.Contract;
import com.hibernate.hrm.entity.ContractAttachment;
import com.hibernate.hrm.entity.User;
import com.hibernate.hrm.entity.dto.contract.ContractAttachmentDTO;
import jakarta.persistence.EntityNotFoundException;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class ContractAttachmentServiceImpl implements ContractAttachmentService {

    private final ContractAttachmentRepository attachmentRepository;
    private final ContractRepository contractRepository;
    private final UserRepository userRepository;

    @Value("${file.upload-dir}")
    private String uploadDir;

    @Override
    public List<ContractAttachmentDTO> getAttachmentsByContractId(Integer contractId) {
        return attachmentRepository.findAllByContractIdOrderByCreateTimeDesc(contractId)
                .stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }

    @Override
    @Transactional
    public ContractAttachmentDTO uploadAttachment(Integer contractId, MultipartFile file, Integer uploaderId) {
        Contract contract = contractRepository.findById(contractId)
                .orElseThrow(() -> new EntityNotFoundException("合同不存在"));
        User uploader = userRepository.findById(uploaderId)
                .orElseThrow(() -> new EntityNotFoundException("用户不存在"));

        try {
            // 确保上传目录存在
            Path uploadPath = Paths.get(uploadDir);
            if (!Files.exists(uploadPath)) {
                Files.createDirectories(uploadPath);
            }

            // 生成唯一文件名
            String originalFilename = file.getOriginalFilename();
            String fileExtension = originalFilename.substring(originalFilename.lastIndexOf("."));
            String uniqueFileName = UUID.randomUUID().toString() + fileExtension;
            Path filePath = uploadPath.resolve(uniqueFileName);

            // 保存文件
            Files.copy(file.getInputStream(), filePath);

            // 保存附件记录
            ContractAttachment attachment = new ContractAttachment();
            attachment.setContract(contract);
            attachment.setFileName(originalFilename);
            attachment.setFilePath(filePath.toString());
            attachment.setFileType(file.getContentType());
            attachment.setUploader(uploader);
            attachment.setCreateTime(LocalDateTime.now());

            ContractAttachment savedAttachment = attachmentRepository.save(attachment);
            return convertToDTO(savedAttachment);
        } catch (IOException e) {
            throw new RuntimeException("文件上传失败", e);
        }
    }

    @Override
    @Transactional
    public void deleteAttachment(Integer contractId, Integer attachmentId) {
        int deletedCount = attachmentRepository.deleteAttachment(contractId, attachmentId);
        if (deletedCount == 0) {
            throw new EntityNotFoundException("附件不存在或不属于该合同");
        }
    }

    private ContractAttachmentDTO convertToDTO(ContractAttachment attachment) {
        ContractAttachmentDTO dto = new ContractAttachmentDTO();
        dto.setAttachmentId(attachment.getAttachmentId());
        dto.setFileName(attachment.getFileName());
        dto.setFileType(attachment.getFileType());
        dto.setUploaderName(attachment.getUploader().getRealName());
        dto.setCreateTime(attachment.getCreateTime());
        dto.setFilePath(attachment.getFilePath());
        return dto;
    }
}
